package com.scexample.template;

import com.scexample.common.PayTypeEnum;
import com.scexample.common.Result;
import com.scexample.pojo.GenericShop;
import com.scexample.pojo.PublicModel;
import lombok.AllArgsConstructor;
import lombok.Data;

import java.util.Objects;

import static com.scexample.common.Constant.*;

/**
 * @program: scexample
 * @description: 进件template
 * @author: 少男
 * @create: 2021-01-18 14:12
 **/
public abstract class AbstractMerchantTemplate {

    private final ThreadLocal<MerchantConfigContext> context = new ThreadLocal<>();

    private MerchantConfigContext merchantConfigContext;

    @Deprecated
    private PublicModel publicModel;


    AbstractMerchantTemplate(Byte payPlatformCode) {
        if (Objects.nonNull(context.get())) {
            Byte inTypeCode = context.get().getPayPlatformCode();

            //不同支付渠道参数切换
            if (!Objects.equals(payPlatformCode, inTypeCode)) {
                remove();
                this.merchantConfigContext = init(payPlatformCode);
            } else {
                this.merchantConfigContext = context.get();
            }
        }
        this.merchantConfigContext = init(payPlatformCode);
        makeTransferDTO();
    }

    /**
     * for old interface compatible
     * 建议使用{@link AbstractMerchantTemplate#getMerchantConfigContext()}替代
     *
     * @return object
     */
    @Deprecated
    final PublicModel getPublicModel() {
        return this.publicModel;
    }

    /**
     * 上下文获取
     *
     * @return context
     */
    final MerchantConfigContext getMerchantConfigContext() {
        return this.merchantConfigContext;
    }

    /**
     * 过时的内容组装方式，兼容老版支付宝进件调用，使用时请置入当前类构造加载过程中
     */
    @Deprecated
    private void makeTransferDTO() {
        PublicModel transferObj = new PublicModel();
        transferObj.setSystemCode(merchantConfigContext.getSystemCode());
        transferObj.setChannelCode(merchantConfigContext.getChannelCode());
        transferObj.setMethodCode(merchantConfigContext.getMethodCode());
        transferObj.setProductCode(merchantConfigContext.getProductCode());
        transferObj.setSceneCode(merchantConfigContext.getSceneCode());
        this.publicModel = transferObj;
    }

    /**
     * 进件申请
     *
     * @param transferDTO 传输对象
     * @param <T>         泛型
     * @return 返回结果
     */
    public abstract <T extends PublicModel> Result apply(GenericShop<T> transferDTO);

    /**
     * 进件信息修改
     *
     * @param transferDTO 传输对象
     * @param <T>         泛型
     * @return 返回结果
     */
    public abstract <T extends PublicModel> Result update(T transferDTO);

    /**
     * 进件查询
     *
     * @param transferDTO 传输对象
     * @param <T>         泛型
     * @return 返回结果
     */
    public abstract <T extends PublicModel> Result query(T transferDTO);

    /**
     * 进件绑卡
     *
     * @param transferDTO 传输对象
     * @param <T>         泛型
     * @return 返回结果
     */
    public abstract <T extends PublicModel> Result bind(T transferDTO);


    /**
     * 上传图床，按需复用
     *
     * @return 上传结果
     */
    public <T extends PublicModel> Result<String> uploadImg(T transferDTO) {
        return null;
    }

    /**
     * 签名方法(可传入业务日志名称进行打印)，按需复用
     *
     * @return 返回签名
     */
    public <T extends PublicModel> T sign(T transferDTO, String logContent) {
        return null;
    }

    /**
     * 签名方法，按需复用
     *
     * @return 返回签名
     */
    public <T extends PublicModel> T sign(T transferDTO) {
        return null;
    }

    /**
     * internal context class
     * Used to transmit docking parameters
     *
     * @author youngBoy
     */
    @Data
    @AllArgsConstructor
    class MerchantConfigContext {
        /**
         * stop abuse
         */
        private MerchantConfigContext() {
        }

        private String systemCode;
        private String sceneCode;
        private String channelCode;
        private String methodCode;
        private String tranTypeCode;
        private String productCode;
        private Byte payPlatformCode;
    }

    /**
     * init method
     *
     * @return ContentContext
     */
    private MerchantConfigContext init(Byte payPlatformCode) {
        if(Objects.equals(PayTypeEnum.aliPay.getCode(), payPlatformCode)) {
            return new MerchantConfigContext(SYSTEM_CODE, SCENE_CODE, CHANNEL_CODE, METHOD_CODE, TRAN_TYPE_CODE, PRODUCT_CODE, payPlatformCode);
        }

        if(Objects.equals(PayTypeEnum.wxPay.getCode(), payPlatformCode)) {
            return new MerchantConfigContext(SYSTEM_CODE, SCENE_CODE, WX_CHANNEL_CODE, WX_METHOD_CODE, TRAN_TYPE_CODE, PRODUCT_CODE, payPlatformCode);
        }
        return new MerchantConfigContext();
    }

    /**
     * 用于上下文内容销毁使用，gc
     */
    final void remove() {
        if (Objects.nonNull(context.get())) {
            context.remove();
        }
    }
}
